package cn.microvideo.videopf.camera.task;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.http.HttpUtil;
import cn.microvideo.videopf.camera.common.RestResult;
import cn.microvideo.videopf.camera.entity.CtyunOnlineStreamResponse;
import cn.microvideo.videopf.camera.service.CameraService;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.Scheduled;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 摄像机定时任务
 *
 * @author 何欢-oreo
 * @version 1.0.0
 * @date 2020/8/19 16:00
 */
@Configuration
@Slf4j
public class CameraTask {
    /**
     * 摄像机服务注入
     */
    @Resource
    private CameraService cameraService;

    @Value("${second.environment.getCameraList.url}")
    private String secondGetCameraListUrl;

    @Value("${online.valid.duration}")
    private Double onlineValidDuration;

    @Value("${cdn.confirm.camera.expire.day}")
    private Integer cdnConfirmCameraExpireDay;

    /**
     * 日期格式化
     */
    private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

    /**
     * 批量插入当天流媒体确认的摄像机初始数据，每天5:00执行一次
     */
    @Scheduled(cron = "${batch.insert.day.confirm.camera.cron.timer}")
    public void batchInsertDayConfirmCameraTask() {
        log.info("CameraTask.batchInsertDayConfirmCameraTask start...");
        //插入本环境摄像机数据
        int insertNum = cameraService.insertCdnConfirmCameraList();
        log.info("CameraTask.batchInsertDayConfirmCameraTask first environment insertNum = {}", insertNum);
        //获取第二环境摄像机数据并且插入
        String strResult = HttpUtil.get(secondGetCameraListUrl);
        JSONObject jsonObjectResult = JSON.parseObject(strResult);
        String strData = jsonObjectResult.getString("data");
        List<Map> cameraList = JSONArray.parseArray(strData, Map.class);
        int secondInsertNum = cameraService.insertOtherCdnConfirmCameraList(cameraList);
        log.info("CameraTask.batchInsertDayConfirmCameraTask second environment insertNum = {}", secondInsertNum);
        log.info("CameraTask.batchInsertDayConfirmCameraTask end");
    }

    /**
     * 获取流媒体在线流并且更新状态
     */
    @Scheduled(cron = "${get.online.stream.cron.timer}")
    public void getOnlineStreamTask() {
        log.info("CameraTask.getOnlineStreamTask start...");
        List<String> cameras = new ArrayList<>();
        //获取天翼云数据
        RestResult ctyunRestResult;
        try {
            ctyunRestResult = cameraService.getCtyunOnlineStream();
        } catch (Exception e) {
            log.info("调用天翼云监控查询信息异常！");
            ctyunRestResult = new RestResult();
        }
        List<CtyunOnlineStreamResponse> ctyunList = (List<CtyunOnlineStreamResponse>) ctyunRestResult.getData();
        List<String> ctyunCameras = Lists.newArrayList();
        if (CollectionUtil.isNotEmpty(ctyunList)) {
            log.info("调用天翼云查询到{}条在线流信息！", ctyunList.size());

            ctyunList.forEach(item -> {
                ctyunCameras.add(item.getStream());
            });
        }
        if (CollectionUtil.isNotEmpty(ctyunCameras)) {
            cameras.addAll(ctyunCameras);
        }

        //获取腾讯云数据
        RestResult tencentRestResult;
        try {
            tencentRestResult = cameraService.getTencentOnlineStream();
        } catch (Exception e) {
            log.info("调用腾讯云监控查询信息异常！");
            tencentRestResult = new RestResult();
        }
        List<Map> tencentList = (List<Map>) tencentRestResult.getData();
        List<String> tencentCameras = Lists.newArrayList();
        if (CollectionUtil.isNotEmpty(tencentList)) {
            log.info("调用腾讯云查询到{}条在线流信息！", tencentList.size());
            tencentList.forEach(item -> {
                tencentCameras.add(item.get("streamName").toString());
            });
        }
        if (CollectionUtil.isNotEmpty(tencentCameras)) {
            cameras.addAll(tencentCameras);
        }

        //获取阿里云数据
        RestResult aliyunRestResult;
        try {
            aliyunRestResult = cameraService.getAliyunOnlineStream();
        } catch (Exception e) {
            log.error("调用阿里云监控查询信息异常！");
            aliyunRestResult = new RestResult();
        }
        List<String> aliyunList = (List<String>) aliyunRestResult.getData();
        if (CollectionUtil.isNotEmpty(aliyunList)) {
            log.info("调用阿里云查询到{}条在线流信息！", aliyunList.size());
            cameras.addAll(aliyunList);
        }
        cameras.stream().distinct();
        if (CollectionUtil.isNotEmpty(cameras)) {
            log.info("调用云监控查询到{}条在线流信息！", cameras.size());
            int updateNum = cameraService.updateCdnConfirmCameraOnlineDuration(sdf.format(new Date()), cameras);
            log.info("CameraTask.getOnlineStreamTask updateCdnConfirmCameraOnlineDuration updateNum = {}", updateNum);
        }
        log.info("CameraTask.getOnlineStreamTask end");
    }

    /**
     * 根据在线时长批量更新摄像机状态，每天23:40执行一次
     */
    @Scheduled(cron = "${batch.update.camera.status.cron.timer}")
    public void batchUpdateCameraStatusTask() {
        log.info("CameraTask.batchUpdateCameraStatusTask start...");
        int updateNum = cameraService.updateCdnConfirmCameraCameraStatus(sdf.format(new Date()), onlineValidDuration);
        log.info("CameraTask.batchUpdateCameraStatusTask updateCdnConfirmCameraCameraStatus updateNum={}",updateNum);
        log.info("CameraTask.batchUpdateCameraStatusTask end");
    }

    /**
     * 清除几天前的流媒体确认的摄像机数据，每天1:00执行一次
     */
    @Scheduled(cron = "${clear.expire.stream.confirm.camera.cron.timer}")
    public void clearExpireStreamConfirmCameraTask() {
        log.info("CameraTask.clearExpireStreamConfirmCameraTask start...");
        LocalDateTime expireDay = LocalDateTime.now().minusDays(cdnConfirmCameraExpireDay);
        int deleteNum = cameraService.deleteExpireCdnConfirmCameraList(expireDay);
        log.info("CameraTask.clearExpireStreamConfirmCameraTask deleteExpireCdnConfirmCameraList deleteNum={}",deleteNum);
        log.info("CameraTask.clearExpireStreamConfirmCameraTask end");
    }
}
